use tonic::{Request, Response, Status};
use tonic::transport::Server;
use async_trait::async_trait;
use crate::service::calculator_server::{Calculator, CalculatorServer};
use crate::service::fs_protocol_lib_server::{FsProtocolLib,FsProtocolLibServer};

pub mod service {
    tonic::include_proto!("calculator");
    tonic::include_proto!("fs_protocol_lib");
}

pub struct MyImplementation;

pub struct MyFsProtocolLib;

#[async_trait]
impl Calculator for MyImplementation {
    async fn add(&self, request: Request<service::Request>) -> Result<Response<service::Result>, Status> {
        let service::Request { x, y } = request.into_inner();
        Ok(Response::new(service::Result { result: x + y }))
    }

    async fn subtract(&self, request: Request<service::Request>) -> Result<Response<service::Result>, Status> {
        let service::Request { x, y } = request.into_inner();
        Ok(Response::new(service::Result { result: x - y }))
    }
}

#[async_trait]
impl FsProtocolLib for MyFsProtocolLib {
    async fn login(&self, request: Request<service::LoginRequest>) -> Result<Response<service::Response>, Status> {
        let service::LoginRequest { username, password } = request.into_inner();
        println!("login ${username} ${password}");
        if username != "" && password != "" {
            return Ok(Response::new(service::Response { msg: "LoginRequest".to_owned(), code: service::Code::Ok.into(), data: None }));
        }
        Ok(Response::new(service::Response { msg: "LoginRequest".to_owned(), code: service::Code::InvalidUsername.into(), data: None }))
    }

    async fn upgrade(&self, request: Request<service::UpgradeRequest>) -> Result<Response<service::Response>, Status> {
        Ok(Response::new(service::Response { msg: "UpgradeRequest".to_owned(), code: service::Code::InvalidUsername.into(), data: None }))
    }
}

#[tokio::main]
async fn main() {
    Server::builder().
        add_service(CalculatorServer::new(MyImplementation)).
        add_service(FsProtocolLibServer::new(MyFsProtocolLib)).
        serve("0.0.0.0:8989".parse()
            .expect("err")).
        await.unwrap();
}